package com.alibaba.citrus.cr.sales.plan.repository;

import com.alibaba.citrus.cr.common.annotation.RepositoryInvoker;
import com.alibaba.citrus.cr.common.util.CalculatePercentage;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.PageQueryPlanLineRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.QuerySalesPlanLineRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.SalesPlanBatchQueryRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.SalesPlanDetailBatchQueryRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.SalesPlanSubTotalRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.response.SalesPlanSubTotalResponse;
import com.alibaba.citrus.cr.sales.plan.model.SalesPlanLineStatusEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.ContractDifferenceMoneyStampEnum;
import com.alibaba.citrus.cr.sales.plan.model.features.SalesPlanLineFeatures;
import com.alibaba.citrus.cr.sales.plan.repository.request.StatCustomerQueryRequest;
import com.alibaba.citrus.cr.sales.plan.repository.request.StatScItemQueryRequest;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanLineSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanStatCustomerSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanStatScItemSDO;
import com.alibaba.citrus.cr.sales.plan.converter.PlanCustomerConverter;
import com.alibaba.citrus.cr.sales.plan.converter.PlanScItemConverter;
import com.alibaba.citrus.cr.sales.plan.converter.SalesPlanLineConverter;
import com.alibaba.cz.base.tool.StringUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.SalesPlanSDO;
import com.epoch.app.bcorder.sales_plan.salesplandetail.dto.*;
import com.epoch.app.bcorder.sales_plan.salesplandetail.model.SalesPlanDetail;
import com.epoch.app.bcorder.sales_plan.salesplandetail.service.SalesPlanDetailService;
import com.epoch.app.crpricecenter.model.dto.ItemResponse;
import net.sf.json.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author wangyibing
 */
@Component
public class SalesPlanLineRepositoryImpl implements SalesPlanLineRepository {

    private static final Log log = Log.getLogger(SalesPlanLineRepositoryImpl.class);


    @Resource
    private SalesPlanDetailService salesPlanDetailService;

    @Override
    @RepositoryInvoker(printLog = true)
    public String save(SalesPlanLineSDO salesPlanLineSDO) {
        SalesPlanDetail salesPlanDetail = new SalesPlanDetail();
        BeanUtils.copyProperties(salesPlanLineSDO, salesPlanDetail);
        salesPlanDetail.setPlanId(Long.valueOf(salesPlanLineSDO.getPlanId()));
        String features = JSON.toJSONString(salesPlanLineSDO.getSalesPlanLineFeatures());
        salesPlanDetail.setFeatures(features);
        CreateSalesPlanDetailResponse detailResponse = salesPlanDetailService.createSalesPlanDetail(salesPlanDetail);
        return detailResponse.getLastInsertId();
    }


    @Override
    @RepositoryInvoker(printLog = true)
    public SalesPlanLineSDO querySalesPlanLine(QuerySalesPlanLineRequest querySalesPlanLineRequest) {
        LoadSalesPlanDetailRequest loadSalesPlanDetailRequest = new LoadSalesPlanDetailRequest();
        BeanUtils.copyProperties(querySalesPlanLineRequest, loadSalesPlanDetailRequest);
        SalesPlanDetail salesPlanDetail = salesPlanDetailService.loadSalesPlanDetail(loadSalesPlanDetailRequest);
        return SalesPlanLineConverter.planLineDoToSdo(salesPlanDetail);
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public Integer edit(SalesPlanLineSDO salesPlanLineSDO) {
        SalesPlanDetail salesPlanDetail = new SalesPlanDetail();
        BeanUtils.copyProperties(salesPlanLineSDO, salesPlanDetail);
        salesPlanDetail.setPlanId(Long.valueOf(salesPlanLineSDO.getPlanId()));
        UpdateSalesPlanDetailResponse response = salesPlanDetailService.updateSalesPlanDetail(salesPlanDetail);
        return response.getCount();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public Integer delete(SalesPlanLineSDO salesPlanLineSDO) {
        /*DeleteSalesPlanDetailRequest deleteSalesPlanDetailRequest = new DeleteSalesPlanDetailRequest();
        deleteSalesPlanDetailRequest.setId(String.valueOf(salesPlanLineSDO.getId()));
        LoadSalesPlanDetailRequest id = LoadSalesPlanDetailRequest.newBuilder().id(String.valueOf(salesPlanLineSDO.getId())).build();
        SalesPlanDetail salesPlanDetail = salesPlanDetailService.loadSalesPlanDetail(id);
        salesPlanDetail.setStatus(-1);
        UpdateSalesPlanDetailResponse updateSalesPlanDetailResponse = salesPlanDetailService.updateSalesPlanDetail(salesPlanDetail);
        return updateSalesPlanDetailResponse.getCount();*/
        return 0;
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public Integer updateInitTaskCount(Long planId) {
        BatchUpdateInitTaskCountRequest batchUpdateInitTaskCountRequest = new BatchUpdateInitTaskCountRequest();
        batchUpdateInitTaskCountRequest.setPlanId(planId);
        BatchUpdateInitTaskCountResponse response = salesPlanDetailService.batchUpdateInitTaskCount(batchUpdateInitTaskCountRequest);
        return response.getCount();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public String batchCreateSalesPlanLine(List<SalesPlanLineSDO> createPlanLineSDOList) {
        List<SalesPlanDetail> salesPlanDetails = createPlanLineSDOList.stream().map(x->{
            SalesPlanDetail po = new SalesPlanDetail();
            BeanUtils.copyProperties(x, po);
            po.setPlanId(StringUtil.isNotEmpty(x.getPlanId())?Long.parseLong(x.getPlanId()):null);
            po.setVersion(1);
            return po;
        }).collect(Collectors.toList());
        BatchCreateSalesPlanDetailRequest planDetailRequest = BatchCreateSalesPlanDetailRequest.builder()
                .salesPlanDetails(salesPlanDetails).build();
        BatchCreateSalesPlanDetailResponse response = salesPlanDetailService.batchCreateSalesPlanDetail(planDetailRequest);
        return response.getTotal().toString();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public PageResult<List<SalesPlanLineSDO>> pageQuerySalesPlanLineList(PageQueryPlanLineRequest pageQuerySalePlanRequest) {
        LoadSalesPlanDetailListRequest salesPlanDetailLoadListRequest = new LoadSalesPlanDetailListRequest();
        BeanUtils.copyProperties(pageQuerySalePlanRequest, salesPlanDetailLoadListRequest);
        salesPlanDetailLoadListRequest.setPlanId(Long.valueOf(pageQuerySalePlanRequest.getPlanId()));
        if (ContractDifferenceMoneyStampEnum.SATISFY.getStamp().equals(pageQuerySalePlanRequest.getContractDifferenceMoneyStamp())) {
            salesPlanDetailLoadListRequest.setGtSatisfy(0);
        } else if (ContractDifferenceMoneyStampEnum.DISSATISFY.getStamp().equals(pageQuerySalePlanRequest.getContractDifferenceMoneyStamp())) {
            salesPlanDetailLoadListRequest.setLtSatisfy(0);
        }
        Result<List<SalesPlanDetail>> listResult = salesPlanDetailService.loadSalesPlanDetailList(salesPlanDetailLoadListRequest);
        List<SalesPlanLineSDO> collect = listResult.getResult().stream().map(salesPlanDetail -> SalesPlanLineConverter.planLineDoToSdo(salesPlanDetail)).collect(Collectors.toList());
        return PageResult.of(collect, listResult.getTotal());
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public SalesPlanSubTotalResponse subTotalSalesPlanLine(SubTotalSalesPlanLineRequest subTotalSalesPlanLineRequest) {
        SubTotalSalesPlanLineResponse subTotalStatResponse = salesPlanDetailService.subTotalSalesPlanLine(subTotalSalesPlanLineRequest);
        SalesPlanSubTotalResponse salesPlanSubTotalResponse = SalesPlanSubTotalResponse.builder().build();
        BeanUtils.copyProperties(subTotalStatResponse, salesPlanSubTotalResponse);
        salesPlanSubTotalResponse.setPlanId(subTotalSalesPlanLineRequest.getPlanId());
        return salesPlanSubTotalResponse;
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public BigDecimal queryCompletePercent(SalesPlanSubTotalRequest salesPlanSubTotalRequest) {
        QueryCompletePercentRequest queryCompletePercentRequest = new QueryCompletePercentRequest();
        BeanUtils.copyProperties(salesPlanSubTotalRequest, queryCompletePercentRequest);
        //全部
        QueryCompletePercentResponse allPercentResponse = salesPlanDetailService.queryCompletePercent(queryCompletePercentRequest);
        if (allPercentResponse != null && allPercentResponse.getCount() != 0) {
            //未完成
            List<Integer> statusList = new ArrayList();
            statusList.add(SalesPlanLineStatusEnum.DRAFT.getStatus());
            queryCompletePercentRequest.setStatusList(statusList);
            QueryCompletePercentResponse toBeLockedPercentResponse = salesPlanDetailService.queryCompletePercent(queryCompletePercentRequest);
            Long toBeLockedCount = toBeLockedPercentResponse.getCount() != null ? toBeLockedPercentResponse.getCount() : 0L;
            return CalculatePercentage.retainTwo(allPercentResponse.getCount() - toBeLockedCount, allPercentResponse.getCount());
        }
        return new BigDecimal("0");
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public List<String> querySalesPlanLineByCustomerAddress(SalesPlanSubTotalRequest salesPlanSubTotalRequest) {
        QueryCustomerAddressSalesPlanDetailRequest queryCustomerAddressSalesPlanDetailRequest = new QueryCustomerAddressSalesPlanDetailRequest();
        BeanUtils.copyProperties(salesPlanSubTotalRequest, queryCustomerAddressSalesPlanDetailRequest);
        return salesPlanDetailService.queryCustomerAddressSalesPlanDetail(queryCustomerAddressSalesPlanDetailRequest).getResult();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public List<SalesPlanLineSDO> batchQueryDetailByIds(SalesPlanDetailBatchQueryRequest salesPlanDetailBatchQueryRequest) {
        Integer pageSize = 1000;
        BatchQueryDetailByIdsRequest batchQueryDetailByIdsRequest = BatchQueryDetailByIdsRequest.builder()
                .ids(salesPlanDetailBatchQueryRequest.getIds())
                .planIds(salesPlanDetailBatchQueryRequest.getPlanIds())
                .scItemIds(salesPlanDetailBatchQueryRequest.getScItemIds())
                .customerAddress(salesPlanDetailBatchQueryRequest.getCustomerAddress())
                .customerAddressIds(salesPlanDetailBatchQueryRequest.getCustomerAddressIds())
                .build();
        batchQueryDetailByIdsRequest.setStart(0);
        batchQueryDetailByIdsRequest.setLimit(pageSize);
        BatchQueryDetailByIdsResponse batchQueryDetailByIdsResponse = salesPlanDetailService.batchQueryDetailByIds(batchQueryDetailByIdsRequest);
        List<SalesPlanDetail> salesPlanDetailList = batchQueryDetailByIdsResponse.getResult();
        if(batchQueryDetailByIdsResponse.getTotal() > pageSize){
            Integer page = (batchQueryDetailByIdsResponse.getTotal() + pageSize - 1)/pageSize;
            for (int i = 1; i < page; i++) {
                batchQueryDetailByIdsRequest.setStart(i*pageSize);
                BatchQueryDetailByIdsResponse response = salesPlanDetailService.batchQueryDetailByIds(batchQueryDetailByIdsRequest);
                salesPlanDetailList.addAll(response.getResult());
            }
        }
        List<SalesPlanLineSDO> salesPlanLineSDOS = salesPlanDetailList.stream().map(salesPlanDetail -> SalesPlanLineConverter.planLineDoToSdo(salesPlanDetail)).collect(Collectors.toList());
        return salesPlanLineSDOS;
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public List<SalesPlanLineSDO> batchQueryDetail(SalesPlanBatchQueryRequest salesPlanBatchQueryRequest) {
        BatchQueryDetailRequest batchQueryDetailRequest = BatchQueryDetailRequest.builder()
                .planId(Long.valueOf(salesPlanBatchQueryRequest.getPlanId()))
                .orgBusinessUnitCode(salesPlanBatchQueryRequest.getOrgBusinessUnitCode())
                .orgSalesOrganizationCode(salesPlanBatchQueryRequest.getOrgSalesOrganizationCode())
                .orgSalesChannelCode(salesPlanBatchQueryRequest.getOrgSalesChannelCode())
                .orgSalesDepartmentCode(salesPlanBatchQueryRequest.getOrgSalesDepartmentCode())
                .ids(salesPlanBatchQueryRequest.getIds())
                .scItemId(salesPlanBatchQueryRequest.getScItemId())
                .build();
        Result<List<SalesPlanDetail>> batchQueryDetail = salesPlanDetailService.batchQueryDetail(batchQueryDetailRequest);
        List<SalesPlanLineSDO> salesPlanLineSDOList = batchQueryDetail.getResult().stream().map(salesPlanDetail -> SalesPlanLineConverter.planLineDoToSdo(salesPlanDetail)).collect(Collectors.toList());
        return salesPlanLineSDOList;
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public List<String> querySalesPlanLineByScItem(SalesPlanSubTotalRequest salesPlanSubTotalRequest) {
        QueryScItemSalesPlanDetailRequest queryScItemSalesPlanDetailRequest = new QueryScItemSalesPlanDetailRequest();
        BeanUtils.copyProperties(salesPlanSubTotalRequest, queryScItemSalesPlanDetailRequest);
        return salesPlanDetailService.queryScItemSalesPlanDetail(queryScItemSalesPlanDetailRequest).getResult();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public PageResult<List<SalesPlanLineSDO>> pageQuerySalesPlanLineAdjustAddList(PageQueryPlanLineRequest pageQuerySalePlanRequest) {
        LoadSalesPlanDetailAdjustAddListRequest salesPlanDetailAdjustAddListRequest = new LoadSalesPlanDetailAdjustAddListRequest();
        BeanUtils.copyProperties(pageQuerySalePlanRequest, salesPlanDetailAdjustAddListRequest);
        salesPlanDetailAdjustAddListRequest.setPlanId(Long.valueOf(pageQuerySalePlanRequest.getPlanId()));
        if (ContractDifferenceMoneyStampEnum.SATISFY.getStamp().equals(pageQuerySalePlanRequest.getContractDifferenceMoneyStamp())) {
            salesPlanDetailAdjustAddListRequest.setGtSatisfy(0);
        } else if (ContractDifferenceMoneyStampEnum.DISSATISFY.getStamp().equals(pageQuerySalePlanRequest.getContractDifferenceMoneyStamp())) {
            salesPlanDetailAdjustAddListRequest.setLtSatisfy(0);
        }
        Result<List<SalesPlanDetail>> listResult = salesPlanDetailService.loadSalesPlanDetailAdjustAddList(salesPlanDetailAdjustAddListRequest);
        List<SalesPlanLineSDO> collect = listResult.getResult().stream().map(salesPlanDetail -> SalesPlanLineConverter.planLineDoToSdo(salesPlanDetail)).collect(Collectors.toList());
        return PageResult.of(collect, listResult.getTotal());
    }

    @Override
    public Integer batchUpdateById(List<SalesPlanLineSDO> request) {
        if (CollectionUtils.isEmpty(request)){
            return 0;
        }
        BatchUpdateSalesPlanDetailRequest detailRequest = new BatchUpdateSalesPlanDetailRequest();
        detailRequest.setSalesPlanDetails(SalesPlanLineConverter.planLineSdoToDoList(request));
        BatchUpdateSalesPlanDetailResponse batchUpdateSalesPlanDetailResponse = salesPlanDetailService.batchUpdateSalesPlanDetail(detailRequest);
        if (batchUpdateSalesPlanDetailResponse == null){
            log.error("SalesPlanLineRepositoryImpl.batchUpdateById failed");
            return 0;
        }
        if (batchUpdateSalesPlanDetailResponse.getError() != null && batchUpdateSalesPlanDetailResponse.getError() > 0){
            log.error("SalesPlanLineRepositoryImpl.batchUpdateById result:"+batchUpdateSalesPlanDetailResponse);
        }
        return batchUpdateSalesPlanDetailResponse.getSuccess();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public Integer queryPlanCustomerCount(Long planId, List<Integer> statusList) {
        PlanCustomerStatCountRequest request = new PlanCustomerStatCountRequest();
        request.setPlanId(planId);
        request.setStatusList(statusList);
        PlanCustomerStatCountResponse planCustomerStatCountResponse = salesPlanDetailService.planCustomerStatCount(request);
        if (planCustomerStatCountResponse != null) {
            return planCustomerStatCountResponse.getCount();
        }
        return null;
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public Integer batchUpdateLineStatus(List<SalesPlanLineSDO> salesPlanLineSDOList) {
        List<Long> ids = salesPlanLineSDOList.stream().map(SalesPlanLineSDO::getId).collect(Collectors.toList());
        BatchUpdateDetailStatusRequest batchUpdateDetailStatusRequest = BatchUpdateDetailStatusRequest.builder().ids(ids)
                .status(SalesPlanLineStatusEnum.DELETE.getStatus()).build();
        BatchUpdateDetailStatusResponse batchUpdateDetailStatusResponse = salesPlanDetailService.batchUpdateDetailStatus(batchUpdateDetailStatusRequest);
        return batchUpdateDetailStatusResponse.getCount();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public List<SalesPlanStatCustomerSDO> queryStatPlanCustomerList(StatCustomerQueryRequest statQueryRequest) {
        PlanCustomerStatRequest request = new PlanCustomerStatRequest();
        request.setPlanId(statQueryRequest.getPlanId());
        request.setStart(statQueryRequest.getStart());
        request.setLimit(statQueryRequest.getLimit());
        request.setStatusList(statQueryRequest.getStatusList());
        PlanCustomerStatResponse planCustomerStatResponse = salesPlanDetailService.planCustomerStat(request);
        if (planCustomerStatResponse != null) {
            return PlanCustomerConverter.planCustomerDoToSdo(planCustomerStatResponse.getResult());
        }
        return null;
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public List<SalesPlanStatScItemSDO> queryStatPlanScItemList(StatScItemQueryRequest statQueryRequest) {
        PlanScItemStatBySalesManRequest request = new PlanScItemStatBySalesManRequest();
        request.setPlanId(Long.valueOf(statQueryRequest.getPlanId()));
        request.setManageEmployee(statQueryRequest.isManageEmployee());
        request.setOrgSalesDepartment(statQueryRequest.isOrgSalesDepartment());
        request.setOrgSalesChannel(statQueryRequest.isOrgSalesChannel());
        request.setOrgSalesOrganization(statQueryRequest.isOrgSalesOrganization());
        request.setOrgBusinessUnit(statQueryRequest.isOrgBusinessUnit());
        request.setStart(statQueryRequest.getStart());
        request.setLimit(statQueryRequest.getLimit());
        PlanScItemStatBySalesManResponse planScItemStatBySalesManResponse = salesPlanDetailService.planScItemStatBySalesMan(request);
        if (planScItemStatBySalesManResponse != null) {
            return PlanScItemConverter.planScItemDoToSdo(planScItemStatBySalesManResponse.getResult());
        }
        return null;
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public Map<Long,SalesPlanSDO> statisticalPlanDetailCount(List<Long> planIdList){
        StatisticalPlanDetailCountRequest statisticalPlanDetailCountRequest = new StatisticalPlanDetailCountRequest();
        statisticalPlanDetailCountRequest.setPlanIdList(planIdList);
        Result<List<SalesPlanSDO>> result = salesPlanDetailService.statisticalPlanDetailCount(statisticalPlanDetailCountRequest);
        if (result != null && CollectionUtils.isNotEmpty(result.getResult())) {
            Map<Long,SalesPlanSDO> map = result.getResult().stream().collect(Collectors.toMap(SalesPlanSDO::getId, Function.identity(),(v1, v2)->v1));
            return map;
        }
        return new HashMap<>();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public Long queryMaxPlanLineNo(Long planId){
        QueryMaxPlanLineNoRequest request = new QueryMaxPlanLineNoRequest();
        request.setPlanId(planId);
        QueryMaxPlanLineNoResponse response = salesPlanDetailService.queryMaxPlanLineNo(request);
        return response.getMaxLineNo();
    }

}
